﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MoneyWentWhere.DataModel;
using System.IO;
using MoneyWentWhere.WinFormsUI.Properties;
using MoneyWentWhere.DataModel.Storage;
using System.Threading;
using System.Diagnostics;
using MoneyWentWhere.WinFormsUI.UI;
using MoneyWentWhere.WinFormsUI.Reports;

namespace MoneyWentWhere.WinFormsUI
{
    public partial class MainForm : Form
    {
        FileManager _fm = new FileManager();

        public MoneyDataSet DataSet
        {
            get { return _fm.DataSet; }
            set 
            {
                if (_fm.DataSet != null) 
                { 
                    _fm.DataSet.Dispose();
                    _fm.DataSet = null;
                }
                _fm.DataSet = value; 
            }
        }


        public MainForm()
        {
            InitializeComponent();
            LoadUISettings();
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            BindDataSources();
        }

        void LoadUISettings()
        {
            autoSaveToolStripMenuItem.Checked = Settings.Default.AutoSave;
        }

        void UpdateTitle()
        {
            Text = String.Format(Resources.AppTitle, Path.GetFileName(DataSet.Filename));
        }

        void BindDataSources()
        {
            UpdateTitle();

            accountListBS.DataSource = DataSet.Accounts;
            accountPage.Account = lbAccts.SelectedItem as Account;
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (PromptAndSave(!AutoSave) == DialogResult.Cancel) 
            { 
                e.Cancel = true;
                return;
            }

            Settings.Default.Save();
        }

        /// <summary>
        /// Save the file, and optionally prompt for the name.
        /// 
        /// Returns Yes for saved, No for not saved, 
        /// Cancel for not saved and cancel the operation.
        /// </summary>
        /// <param name="showPrompt"></param>
        /// <returns></returns>
        DialogResult PromptAndSave(bool showPrompt)
        {
            // Promot to save yes/no/cancel
            if (showPrompt)
            {
                String p = String.Format(Resources.saveChangesPrompt, _fm.DataSet.Filename);
                DialogResult dr =
                    MessageBox.Show(this, p, Text, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dr == DialogResult.Cancel || dr == DialogResult.No) { return dr; }
            }

            // BUG: If we add a new row without starting to edit, it doesn't get saved
            if (accountPage.dgTransactions.IsCurrentCellInEditMode)
            {
                accountPage.dgTransactions.CommitEdit(DataGridViewDataErrorContexts.Commit);
            }

            try
            {
                _fm.DataSet.Save();
            }
            catch (Exception e)
            {
                MessageBox.Show("Cannot save file.\r\n" + e.Message + "\r\nIf file is open in Excel, please close it and try again.", "Error");
                return DialogResult.Cancel;
            }
            return DialogResult.Yes;
        }

        #region File Menu

        bool AutoSave
        {
            get { return autoSaveToolStripMenuItem.Checked; }
            set { autoSaveToolStripMenuItem.Checked = value; }
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (PromptAndSave(!AutoSave) == DialogResult.Cancel) { return; }

            String name = FileManager.CreateNewFileName(_fm.NewFile);

            // Create and save
            DataSet = new MoneyDataSet(name, DataFormatX.Excel2007); 

            // Re-bind data
            BindDataSources();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (PromptAndSave(!AutoSave) == DialogResult.Cancel) { return; }

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                MoneyDataSet ds;
                bool opened = _fm.TryOpenFile(openFileDialog.FileName, out ds);
                if (opened)
                {
                    _fm.DataSet = ds;

                    // Re-bind sources
                    BindDataSources();

                    // Set as default automatically
                    Settings.Default.StartupFile = openFileDialog.FileName;
                    Settings.Default.Save();
                }
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PromptAndSave(false);
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                DataSet.Save(saveFileDialog.FileName);
                UpdateTitle();
                // No need to re-bind data sources
            }
        }

        private void autoSaveToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Settings.Default.AutoSave = autoSaveToolStripMenuItem.Checked;
            Settings.Default.Save();
        }

        #endregion

        private void passwordToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetPasswordDialog d = new SetPasswordDialog();
            d.FileEncrypted = !String.IsNullOrEmpty(DataSet.Password);

            if (d.ShowDialog(this) == DialogResult.OK)
            {
                if (d.FileEncrypted)
                {
                    // Set or change password                    
                    DataSet.DataFormat = DataFormatX.Excel2007;
                    DataSet.Password = d.Password;

                    // Save immediately for security reasons
                    // (e.g. if app crashes, we don't want an unprotected file)
                    DataSet.Save(DataSet.Filename);
                }
                else
                {
                    // Save as plain file
                    IHasPassword pf = DataSet.DataFormat as IHasPassword;

                    // Plain text already, no need to save
                    if (pf == null) { return; }

                    pf.Password = null;

                    // Switch to non-encrypted format
                    if (DataSet.DataFormat == DataFormatX.EncryptedMwwXml)
                    {
                        DataSet.DataFormat = DataFormatX.MwwXml;
                    }

                    // Unencrypt
                    DataSet.Save(DataSet.Filename);
                }
            }
        }

        private void dgTransactions_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            Trace.WriteLine("Error in row: " + e.RowIndex + " col: " + e.ColumnIndex); 
        }

        private void tbAddAcct_Click(object sender, EventArgs e)
        {
            int num = DataSet.Accounts.Count + 1;
            Account ac = DataSet.CreateAccount("Acct #" + num);

            lbAccts.SelectedItem = ac;

            // BUGFIX: for the first account, page is not 
            // refreshed through SelectedIndexChanged
            if (lbAccts.SelectedIndex == 0) { accountPage.Account = ac; }

            accountPage.tbAcctName.Focus();
            accountPage.tbAcctName.SelectAll();
        }

        private void tbAcctDelete_Click(object sender, EventArgs e)
        {
            Account ac = lbAccts.SelectedItem as Account;
            if (ac == null) { return; }

            if (MessageBox.Show(this, 
                    String.Format(Resources.deleteAcctPrompt, ac.Name), Resources.deleteAcctTitle,
                    MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
            {
                ac.Delete();

                // BUGFIX: for the first account, page is not 
                // refreshed through SelectedIndexChanged
                if (lbAccts.SelectedIndex == 0) { accountPage.Account = lbAccts.SelectedItem as Account; }
                if (lbAccts.SelectedIndex == -1) { accountPage.Account = null; }
            }
        }

        private void lbAccts_SelectedIndexChanged(object sender, EventArgs e)
        {
            // BUGFIX: null SelectedItem occurs on *any* property change
            // (framework refreshes the item). We *must* ignore this.
            if (lbAccts.SelectedItem == null) { return; }

            accountPage.Account = lbAccts.SelectedItem as Account;
        }

        private void tbAcctUp_Click(object sender, EventArgs e)
        {
            Account ac = lbAccts.SelectedItem as Account;
            if (ac == null) { return; }

            int index = DataSet.Accounts.IndexOf(ac);
            if (index == 0) { return; }
            DataSet.Accounts.Move(index, index - 1);
            lbAccts.SelectedItem = ac;
        }

        private void tbAcctDown_Click(object sender, EventArgs e)
        {
            Account ac = lbAccts.SelectedItem as Account;
            if (ac == null) { return; }

            int index = DataSet.Accounts.IndexOf(ac);
            if (index >= DataSet.Accounts.Count - 1) { return; }
            DataSet.Accounts.Move(index, index + 1);
            lbAccts.SelectedItem = ac;
        }

        private void bShowAnalysis_Click(object sender, EventArgs e)
        {
            ShowReport(new AccountBalanceReport());
        }

        private void bExpenses_Click(object sender, EventArgs e)
        {
            ShowReport(new ExpenseReport());
        }

        void ShowReport(ReportType report)
        {
            ReportForm f = new ReportForm();
            f.panel.ReportType = report;
            f.panel.DataSet = DataSet;
            f.Show();
        }



    }
}
